<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas图片简单处理</title>
</head>
<body>
    <div>
        <button onclick="onReverse()">左右反转</button>
        <button onclick="onMosaic()">马赛克</button>
        <button onclick="onPartMosaic()">局部马赛克</button>
    </div>
    <canvas id="cvs" draggable="true"></canvas>
</body>
<script>
    const cvs = document.querySelector('#cvs')
    const ctx = cvs.getContext('2d')
    const img = new Image()
    img.src = './images/girl.png'
    img.onload = () => {
        cvs.width = img.width / 2
        cvs.height = img.height / 2
        ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
    }
    // 反转
    function onReverse() {
        const imgData = ctx.getImageData(0, 0, cvs.width, cvs.height)
        const data = imgData.data
        const w = cvs.width * 4
        for (let i = 0; i < data.length; i += 4) {

            const r = data[i]
            const g = data[i + 1]
            const b = data[i + 2]
            const a = data[i + 3]
            // 左右等比位置的像素交换
            if (i % w < w / 2) {
                const newI = i + (w - i % w * 2)

                data[i] = data[newI]
                data[i + 1] = data[newI + 1]
                data[i + 2] = data[newI + 2]
                data[i + 3] = data[newI + 3]

                data[newI] = r
                data[newI + 1] = g
                data[newI + 2] = b
                data[newI + 3] = a
            }

        }
        ctx.putImageData(imgData, 0, 0)
    }
    let isMosaic = false
    // 马赛克
    function onMosaic() {
        // 马赛克比例
        const bl = 20
        if (isMosaic) {
            isMosaic = false
            return ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
        }
        isMosaic = true
        const imgData = ctx.getImageData(0, 0, cvs.width, cvs.height)
        const data = imgData.data
        for (let i = 0; i < data.length; i += 4 * bl) {
            for (let b = 0; b < bl; b++) {
                data[i + b * 4] = data[i]
                data[i + 1 + b * 4] = data[i + 1]
                data[i + 2 + b * 4] = data[i + 2]
                data[i + 3 + b * 4] = data[i + 3]
            }
        }
        ctx.putImageData(imgData, 0, 0)
    }
    // 局部马赛克
    function onPartMosaic() {
        // 马赛克比例
        const bl = 10
        // 马赛克区域
        const parts = [
            {
                partX: 200,
                partY: 100,
                partWidth: 250,
                partHeight: 100
            },
            {
                partX: 270,
                partY: 242,
                partWidth: 90,
                partHeight: 50
            }
        ]

        if (isMosaic) {
            isMosaic = false
            return ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
        }
        isMosaic = true
        const imgData = ctx.getImageData(0, 0, cvs.width, cvs.height)
        const data = imgData.data
        for (let i = 0; i < data.length; i += 4 * bl) {
            const x = (i / 4) % cvs.width
            const y = parseInt((i / 4) / cvs.width)
            // 有一个返回true，则result为true
            const result = parts.some(v => {
                return x >= v.partX && x <= v.partX + v.partWidth && y >= v.partY && y <= v.partY + v.partHeight
            })
            if (result) {
                for (let b = 0; b < bl; b++) {
                    data[i + b * 4] = data[i]
                    data[i + 1 + b * 4] = data[i + 1]
                    data[i + 2 + b * 4] = data[i + 2]
                    data[i + 3 + b * 4] = data[i + 3]
                }
            }
        }
        ctx.putImageData(imgData, 0, 0)
    }
</script>

</html>